#include "Logger.h"
#include <stdarg.h>

Logger *Logger::getInstance()
{
    static Logger logger;
    return &logger;
}

std::shared_ptr<spdlog::logger> Logger::getLogger()
{
    return logger_;
}
std::string Logger::formatToString(const char *format, ...)
{
    char buf[1024];
    va_list args;
    va_start(args, format);
    vsprintf(buf, format, args);
    va_end(args);
    return buf;
}
std::string Logger::currentTimeAsString()
{
    std::time_t now =
        std::chrono::system_clock::to_time_t(std::chrono::system_clock::now());

    char buf[100] = {0};
    std::strftime(buf, sizeof(buf), "%Y-%m-%d-%H-%M-%S", std::localtime(&now));
    return buf;
}

Logger::Logger()
{
    const std::string kLogDir = "./log";
    const std::string kLoggerNamePrefix = "log_";

    bool console = false;

    std::string level = "trace";

    try
    {

        const std::string kLoggerName = currentTimeAsString();

        if (console)
            logger_ = spdlog::stdout_color_st(kLoggerName);
        else
            logger_ =
                spdlog::create_async<spdlog::sinks::rotating_file_sink_mt>(
                    kLoggerName, kLogDir + "/" + kLoggerName + ".log",
                    500 * 1024 * 1024, 1000);

        // custom format
        logger_->set_pattern(
            "%Y-%m-%d %H:%M:%S <thread %t> [%l] [%@] [%!] %v"); // with
                                                                // timestamp,
                                                                // thread_id,
                                                                // filename and
                                                                // line number
        if (level == "trace")
        {
            logger_->set_level(spdlog::level::trace);
            logger_->flush_on(spdlog::level::trace);
        }
        else if (level == "debug")
        {
            logger_->set_level(spdlog::level::debug);
            logger_->flush_on(spdlog::level::debug);
        }
        else if (level == "info")
        {
            logger_->set_level(spdlog::level::info);
            logger_->flush_on(spdlog::level::info);
        }
        else if (level == "error")
        {
            logger_->set_level(spdlog::level::err);
            logger_->flush_on(spdlog::level::err);
        }
        else if (level == "fatal")
        {
            logger_->set_level(spdlog::level::critical);
            logger_->flush_on(spdlog::level::critical);
        }
    }
    catch (const spdlog::spdlog_ex &ex)
    {
        std::cout << "Log initialization failed: " << ex.what() << std::endl;
    }
}

Logger::~Logger()
{
    spdlog::drop_all();
}
